﻿using LiveCharts;
using Ping9719.WpfEx;
using Ping9719.WpfEx.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;

namespace BaseUi.ViewModel
{
    public class HomeViewModel : BindableBase
    {
        CancellationTokenSource cancellationToken = null;//停止
        ManualResetEvent manualReset = null;//暂停、继续
        WarnInfoContainer WarnInfo = new WarnInfoContainer();//警告、错误等信息

        #region 绑定
        private string textErr;
        /// <summary>
        /// 错误文本
        /// </summary>
        public string TextErr { get => textErr; set { SetProperty(ref textErr, value); } }
        public ICommand ClearTextInfoCommand { get => new DelegateCommand(ClearTextInfo); }
        /// <summary>
        /// 清除信息文本
        /// </summary>
        public void ClearTextInfo()
        {
            TextBoxLog.ClearLog();
        }
        public ICommand ClearTextErrCommand { get => new DelegateCommand(ClearTextErr); }
        /// <summary>
        /// 清除全部错误文本
        /// </summary>
        public void ClearTextErr()
        {
            WarnInfo.RemoveAll(WarnInfoType.AlwayWarn);
        }
        #endregion

        #region 页面加载时任务
        /// <summary>
        /// 页面第一次加载时执行的任务
        /// </summary>
        public void LoadTask()
        {
            //注册警告事件
            WarnInfo.WarnInfoChanged += (all, add, rem) =>
            {
                TextErr = string.Join(Environment.NewLine, all.OrderBy(o => (o.WarnType, o.Source, o.Text)));

                if (add.Any())
                    Logs.Write(add.Select(o => o.ToString()), LogsType.Warning);
                if (rem.Any())
                    Logs.Write(rem.Select(o => o.ToString()), LogsType.Warning);

                //警告信息保存到数据库
                //WarnInfoDb.db.Insertable(WarnInfoItemDb.GetList(add)).ExecuteCommand();
                //WarnInfoDb.db.Updateable(WarnInfoItemDb.GetList(rem)).ExecuteCommand();
            };

            Task.Run(PlcErrListen);
        }

        /// <summary>
        /// 根据Excel里面的内容监听plc错误信息
        /// </summary>
        async void PlcErrListen()
        {
            //Excel解析的错误格式
            var excelErrAll = ExcelDeviceAlarmModel.GetDatas();
            while (true)
            {
                List<ExcelDeviceAlarmModel> excelErr = new List<ExcelDeviceAlarmModel>();
                foreach (var item in excelErrAll)
                {
                    object? val = null;
                    //if (item.类型.ToLower() == "bool")
                    //{
                    //    var plcInfo = LocalStatic.Plc.Read<bool>(item.地址);
                    //    val = plcInfo.IsSucceed ? plcInfo.Value : null;
                    //}
                    //else if (item.类型.ToLower() == "int")
                    //{
                    //    var plcInfo = LocalStatic.Plc.Read<Int16>(item.地址);
                    //    val = plcInfo.IsSucceed ? plcInfo.Value : null;
                    //}

                    if (item.IsOnAlarm(val))
                        excelErr.Add(item);
                }

                WarnInfo.AddOrUpdate(excelErr.Select(o => new WarnInfoItem()
                {
                    Source = "PLC",
                    Text = o.名称,
                    WarnType = WarnInfoType.WhileWarn,
                    Level = o.级别,
                    Solution = o.解决方式
                }));

                await Task.Delay(500);
            }
        }
        #endregion

        #region 业务

        private RunState runState = RunState.Stop;
        /// <summary>
        /// 运行状态
        /// </summary>
        public RunState RunState { get => runState; set { SetProperty(ref runState, value); } }

        public ICommand RunStateClickCommand { get => new DelegateCommand<RunStateButtonClick>(RunStateClick); }
        /// <summary>
        /// 运行状态
        /// </summary>
        public void RunStateClick(RunStateButtonClick clickrunState)
        {
            if (clickrunState == RunStateButtonClick.Start)
            {
                TextBoxLog.AddLog("点击开始");
                Start();
            }
            else if (clickrunState == RunStateButtonClick.Pause)
            {
                TextBoxLog.AddLog("点击暂停");
                Pause();
            }
            else if (clickrunState == RunStateButtonClick.Continue)
            {
                TextBoxLog.AddLog("点击继续");
                Continue();
            }
            else if (clickrunState == RunStateButtonClick.Stop)
            {
                TextBoxLog.AddLog("点击停止");
                Stop();
            }
            else if (clickrunState == RunStateButtonClick.Rset)
            {

            }
        }

        /// <summary>
        /// 开始
        /// </summary>
        private void Start()
        {
            cancellationToken = new CancellationTokenSource();
            manualReset = new ManualResetEvent(true);
            Task.Run(Task1);
            RunState = RunState.Run;
        }

        /// <summary>
        /// 暂停
        /// </summary>
        public void Pause()
        {
            manualReset.Reset();
            RunState = RunState.Pause;
        }

        /// <summary>
        /// 继续
        /// </summary>
        public void Continue()
        {
            manualReset.Set();
            RunState = RunState.Run;
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            cancellationToken.Cancel();
            RunState = RunState.Stop;
        }

        private async void Task1()
        {
            //模拟信息
            try
            {
                int i = 1;
                while (true)
                {
                    //1.带条件等待
                    await While.Wait(() =>
                    {
                        return true;
                    }, cancellationToken.Token, manualReset);
                    //2.直接等待
                    While.Wait(cancellationToken.Token, manualReset);

                    TextBoxLog.AddLog(i.ToString());
                    await Task.Delay(500);
                    i++;
                }
            }
            catch (OperationCanceledException)
            {
                TextBoxLog.AddLog("已停止");
            }
            catch (Exception ex)
            {
                TextBoxLog.AddLog($"错误：{ex.ToString()}");
            }
            finally
            {
                cancellationToken?.Cancel();
            }
        }
        #endregion
    }
}
